#include "KeyValueSet.h"
#include <stdexcept>  
#include <cstddef> 
#include "zlib\zlib.h"

#define COL_SEP_STR "\1\1"
#define ROW_SEP_STR "\1\2"
#define TAB_SEP_STR "\1\3"

#define _SetValue(datatype, funcname, value)\
   datatype Value = funcname(value);\
   SetValue(pszName, Value);

#define CREATE_CONTAINER(type, interface_type, ptrDeler) \
	interface_type * ptrRetVal = nullptr;\
	auto CreatePtr = []()->interface_type *\
	{\
		type * ptrVal = new type();\
		if (!ptrVal->Init(nullptr, nullptr, 0))\
		{\
			delete ptrVal;\
			ptrVal = nullptr;\
			return ptrVal;\
		}\
		return dynamic_cast<interface_type *>(ptrVal);\
	};\
	try\
	{\
        unordered_map<string, char *>::iterator it;\
		Lock();\
		if (IsEmpty(pszName))\
		{\
			ptrRetVal = CreatePtr();\
		}\
		else if (_ExistValue(pszName, &it))\
		{\
			ptrRetVal = reinterpret_cast<interface_type *>(GetValAdder(it->second));\
            if (!ptrRetVal) _DelVar(pszName, false);\
		}\
		if (!ptrRetVal)\
		{\
			ptrRetVal = CreatePtr();\
            SetValue(pszName, reinterpret_cast<void *>(ptrRetVal), ptrDeler);\
		}\
	}\
	catch (const std::exception& clErrMsg)\
	{\
	}\
	Unlock();\
	return *ptrRetVal;\

bool IsEmpty(const char * pszStr)
{
	return pszStr == nullptr || pszStr[0] == '\0';
}

int SeparateCount(const char * pszStr, const char * pszSeparateStr)
{
	int iRetVal = 0, iLen = strlen(pszSeparateStr), iBgnPos = 0;
	string strStr(pszStr);
	while ((iBgnPos = strStr.find(pszSeparateStr, iBgnPos) != -1))
	{
		iRetVal++;
		iBgnPos += iLen;
	}
	if (strStr.substr(strStr.length() - iLen, iLen) != pszSeparateStr) iRetVal++;
__end:
	return iRetVal;
}

const char * SeparateString(char * pszResult, int iSize, const char * pszStr, const char * pszSeparateStr, const int iIdx)
{
	memset((void *)pszResult, 0, iSize);
	int iRetVal = 0, iLen = strlen(pszSeparateStr), iBgnPos = 0, iEndPos = 0, 
		iCount = SeparateCount(pszStr, pszSeparateStr);
	string strStr(pszStr);
	if (iIdx <= 0) goto __end;
	if (iCount > iIdx) goto __end;
	while ((iEndPos = strStr.find(pszSeparateStr, iEndPos) != -1))
	{
		iRetVal++;
		if (iRetVal == iIdx)
		{
			iLen = iEndPos - iBgnPos;
			if (iLen != 0)
				memcpy((void *)(pszResult), (void *)strStr.substr(iBgnPos, iLen).c_str(), (iSize - 1) < iLen ? (iSize - 1) : iLen);
			goto __end;
		}
		iEndPos += iLen;
		iBgnPos = iEndPos;
	}
	iLen = strStr.length() - iBgnPos;
	memcpy((void *)(pszResult), (void *)strStr.substr(iBgnPos, iLen).c_str(), (iSize - 1) < iLen ? (iSize - 1) : iLen);
__end:
	return pszResult;
}

int Pos(const char * pszStr, const char * pszSubStr)
{
	int iRetVal = -1;
	const char * pszTmp = strstr(pszStr, pszSubStr);
	if (IsEmpty(pszTmp)) goto __end;
	iRetVal = pszTmp - pszStr;
__end:
	return iRetVal;
}


unordered_map<string, int> CValueSet::m_mpDataTypeId = CValueSet::InitDataTypeId();
unordered_map<int, string> CValueSet::m_mpIdDataType = CValueSet::InitIdDataType();
unordered_map<string, int> CTaskQueue::m_mpDataTypeId = CTaskQueue::InitDataTypeId();
unordered_map<int, string> CTaskQueue::m_mpIdDataType = CTaskQueue::InitIdDataType();

CValueSet::~CValueSet()
{
	DelVar("");
	DeleteCriticalSection(&m_stSection);
}

const bool CValueSet::Init(const void * pvdPara, char * pszMsgTxt, int iMsgTxtSize)
{		
	InitializeCriticalSection(&m_stSection);
	return true;
}

bool CValueSet::Assign(IValueSet * ptrSouValueSet)
{
	bool bRetVal = false;
	CValueSet * ptrValueSet = reinterpret_cast<CValueSet *>(ptrSouValueSet->Self());
	if (!ptrValueSet) return bRetVal;
	try
	{
		Lock();
		ptrValueSet->Lock();
		for (auto itValueInfo : ptrValueSet->m_mpValue)
		{
			char * pszBuffer = new char[BUFFER_LEN];
			bRetVal = (GetTypeId(itValueInfo.second) == 15 || GetTypeId(itValueInfo.second) == 16) ?
				      InitValue(pszBuffer,
						  GetValAdder(itValueInfo.second),
					      GetTypeId(itValueInfo.second),
					      GetValSize(itValueInfo.second),
					      GetDeleter(itValueInfo.second),
					      GetAutoFreeFlg(itValueInfo.second)) :
				      InitValue(pszBuffer,
				       	  GetValAdder(itValueInfo.second),
					      GetTypeId(itValueInfo.second),
					      GetValSize(itValueInfo.second),
					      nullptr,
					      false);
            if (bRetVal)
				m_mpValue[itValueInfo.first] = pszBuffer;
			else
			{
				delete pszBuffer;
				pszBuffer = nullptr;
			}
		}
	}
	catch (...)
	{
	}
__end:
	ptrValueSet->Unlock();
	Unlock();
	return bRetVal;
}
 
void CValueSet::SetKernel(IKernel * ptrKernel)
{
//	m_ptrKernel = ptrKernel;
}

bool CValueSet::ExistValue(const char * pszName)
{
	bool bRetVal = false;
	Lock();
	bRetVal = _ExistValue(pszName, nullptr);
	Unlock();
	return bRetVal;
}

void CValueSet::DelListPtr(void * ptrItme)
{
	IValueSet * ptrVal = reinterpret_cast<IValueSet *>(ptrItme);
	if (ptrVal)
	{
		delete ptrVal;
		ptrVal = nullptr;
	}
}

void CValueSet::DelQueuePtr(void * ptrItme)
{
	//ITaskQueue * ptrVal = reinterpret_cast<ITaskQueue *>(ptrItme);
	//if (ptrVal)
	//{
	//	delete ptrVal;
	//	ptrVal = nullptr;
	//}
}

void CValueSet::DelTablePtr(void * ptrItme)
{
	ITable * ptrVal = reinterpret_cast<ITable *>(ptrItme);
	if (ptrVal)
	{
		delete ptrVal;
		ptrVal = nullptr;
	}
}

IValueSet & CValueSet::List(const char * pszName)
{	
	CREATE_CONTAINER(CValueSet, IValueSet, DelListPtr)
}

ITaskQueue & CValueSet::Queue(const char * pszName)
{
	CREATE_CONTAINER(CTaskQueue, ITaskQueue, DelQueuePtr)
}

//ITable & CValueSet::Table(const char * pszName)
//{
//	CREATE_CONTAINER(CTable, ITable, DelTablePtr) 
//}

const char * CValueSet::DataType(const char * pszName, bool bExistFlg)
{
	const char * pszRetVal = nullptr;
	unordered_map<string, char *>::iterator it;
	try
	{
		Lock();		
		pszRetVal = _ExistValue(pszName, &it) ? m_mpIdDataType[GetTypeId(it->second)].c_str() : "Unknown type.";
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock();
	return pszRetVal;
}

const unsigned long CValueSet::Size(const char * pszName, bool bExistFlg)
{
	unsigned long ulRetVal = 0;
	unordered_map<string, char *>::iterator it;
	try
	{
		Lock();
		ulRetVal = _ExistValue(pszName, &it) ? GetValSize(it->second) : 0;
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock();
	return ulRetVal;
}

const bool CValueSet::GetValNameList(void * vtNameList)
{	
	bool bRetVal = false;
	try
	{
		Lock();
		bRetVal = _GetValNameList(vtNameList);
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock();
__end:
	return bRetVal;
}

const unsigned long CValueSet::ItemCount()
{
	unsigned long ulRetVal = 0;
	try
	{
		Lock();
		ulRetVal = m_mpValue.size();
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock();
__end:
	return ulRetVal;
}

const bool CValueSet::EnCode(char ** pszBuf, unsigned long & ulLen)
{
	bool bRetVal = false;
	vector<string> vtNameList;
	(*pszBuf) = nullptr;
	unsigned long ulBufLen = 0;
	unsigned long ulSize = 0, iCount = 0, iItemLen = 0, iSumLen = SumLength(vtNameList) + 1;
	char szBufLen[CHAR_LEN_MAX_NUM + 1] = { 0 };
	const char * pszDataType = nullptr;
	ulLen = 0;
	if (iSumLen == 0) return bRetVal;
	char * pszData = new char[iSumLen];
	char * pszTemp = pszData;
	string strValue("");
	for (auto it : vtNameList)
	{
		if ((iItemLen = Length(it.c_str())) == 0) continue;
		ulSize      = Size(it.c_str());
		pszDataType = DataType(it.c_str());		
		memset((void *)szBufLen, 0, sizeof(szBufLen));
		ultoa(ulSize, szBufLen, 10);
		memcpy((void *)(pszTemp), (void *)it.c_str(), it.length());
		memcpy((void *)(pszTemp + it.length()), (void *)COL_SEP_STR, strlen(COL_SEP_STR));
		memcpy((void *)(pszTemp + it.length() + strlen(COL_SEP_STR) + ulSize), (void *)COL_SEP_STR, strlen(COL_SEP_STR));
		memcpy((void *)(pszTemp + it.length() + 2 * strlen(COL_SEP_STR) + ulSize + strlen(pszDataType)), (void *)ROW_SEP_STR, strlen(ROW_SEP_STR));
		if (GetValue(it.c_str(), pszTemp + it.length() + strlen(COL_SEP_STR), ulSize))												
			memcpy((void *)(pszTemp + it.length() + 2 * strlen(COL_SEP_STR) + ulSize), (void *)pszDataType, strlen(pszDataType));			
		else
			memset((void *)(pszTemp + it.length() + 2 * strlen(COL_SEP_STR) + ulSize), 49, strlen(pszDataType));
		pszTemp += iItemLen;
	}
	pszData[iSumLen - 1] = 0;
	ulLen = compressBound(iSumLen);
	itoa(iSumLen, szBufLen, 10);
	szBufLen[strlen(szBufLen)] = '|';
	(*pszBuf) = new char[ulLen + strlen(szBufLen)];
	memset((void *)(*pszBuf), 0, ulLen + strlen(szBufLen));
	pszTemp = (*pszBuf) + strlen(szBufLen);
	if (compress((Bytef *)pszTemp, &ulLen, (Bytef *)pszData, iSumLen) != Z_OK)
	{
		delete[](*pszBuf);
		(*pszBuf) = nullptr;
	}	
	else
	{
		memcpy((void *)(*pszBuf), szBufLen, strlen(szBufLen));
		bRetVal = true;
	}
	delete[]pszData;
	pszData = nullptr;		
__end:
	return bRetVal;
}

const bool CValueSet::DeCode(char * pszBuf, unsigned long ulLen)
{	
	bool bRetVal = false;
	auto _GetVal = [](char ** pszData, const char * pszSep)->const char *
	{
		char * pszCurData = strstr((*pszData), COL_SEP_STR);
		(*pszData)[pszCurData - (*pszData)] = '\0';
		const char * pszValue = (*pszData);
		(*pszData) = pszCurData + strlen(COL_SEP_STR);
		return pszValue;
	};
	int i = 0, iCount = 0;
	unsigned long ulDataLen = 0;
	char szDataLen[CHAR_LEN_MAX_NUM] = { 0 };
	char * pszData = nullptr, * pszRowData = nullptr, * pszCurData;
	const char * pszName = nullptr, * pszValue = nullptr, * pszDataType = nullptr;
	void * ptrRecInfo = nullptr;
	if (pszBuf == nullptr) return bRetVal;
	do
	{
		szDataLen[i] = pszBuf[i];
		i++;
	} while (pszBuf[i] != '|');
	pszBuf += i + 1;
	ulDataLen = atoi(szDataLen);
	pszData = new char[ulDataLen];
	if (uncompress((Bytef *)pszData, &ulDataLen, (Bytef *)pszBuf, ulLen) != Z_OK) goto __end;

	while ((pszRowData = strstr(pszData, ROW_SEP_STR)) != nullptr)
	{
		pszData[pszRowData - pszData] = '\0';
		pszName     = _GetVal(&pszData, COL_SEP_STR);
		pszValue    = _GetVal(&pszData, COL_SEP_STR);
		ulDataLen   = pszData - pszValue - strlen(COL_SEP_STR);
		pszDataType = pszData;
		if (strcmp(pszDataType, "double") == 0)
		{
			_SetValue(double, stold, pszValue);
		}
		else if (strcmp(pszDataType, "float") == 0)
		{
			_SetValue(float, stof, pszValue);
		}
		else if (strcmp(pszDataType, "bool") == 0)
		{
			_SetValue(bool, stoi, pszValue);
		}
		else if (strcmp(pszDataType, "int") == 0)
		{
			_SetValue(int, stoi, pszValue);
		}
		else if (strcmp(pszDataType, "unsigned int") == 0)
		{						
			_SetValue(unsigned int, stoul, pszValue);
		}
		else if (strcmp(pszDataType, "long") == 0)
		{
			_SetValue(long, stol, pszValue);
		}
		else if (strcmp(pszDataType, "unsigned long") == 0)
		{
			_SetValue(unsigned long, stoul, pszValue);
		}
		else if (strcmp(pszDataType, "long long") == 0)
		{
			_SetValue(long long, stoll, pszValue);
		}
		else if (strcmp(pszDataType, "unsigned long long") == 0)
		{
			_SetValue(unsigned long long, stoull, pszValue);
		}
		else if (strcmp(pszDataType, "string") == 0)
		{
			SetValue(pszName, move(string(pszValue)));
		}
		else if (strcmp(pszDataType, "char *") == 0 || strcmp(pszDataType, "const char *") == 0)
		{
			SetValue(pszName, pszValue, strlen(pszValue));
		}
		else if (strcmp(pszDataType, "void *") == 0 && ulDataLen > 0)
		{
			SetValue(pszName, (void *)pszValue, ulDataLen);
		}
		pszData = pszRowData + strlen(ROW_SEP_STR);
	}	
	bRetVal = true;
__end:
	return bRetVal;
}

const unsigned long CValueSet::GetSequence()
{
	return m_ulSequence;
}

void CValueSet::SetSequence(const unsigned long ulSequence)
{
	m_ulSequence = ulSequence;
}

void * CValueSet::Self()
{
	return reinterpret_cast<void *>(this);
}

bool CValueSet::GetAutoFreeFlg(char * pszBuffer)
{
	return pszBuffer[0];
}

bool CValueSet::GetBufValue(char * pszBuffer, string & strValue)
{	
	strValue = "";
	int iSouTypeId = GetTypeId(pszBuffer);
	switch (iSouTypeId)
	{
	case 1: { strValue = to_string(*(int *)GetValAdder(pszBuffer)); break; }
	case 2: { strValue = to_string(*(unsigned int *)GetValAdder(pszBuffer)); break; }
	case 3: { strValue = to_string(*(long *)GetValAdder(pszBuffer)); break; }
	case 4: { strValue = to_string(*(unsigned long *)GetValAdder(pszBuffer)); break; }
	case 5: { strValue = to_string(*(long long *)GetValAdder(pszBuffer)); break; }
	case 6: { strValue = to_string(*(unsigned long long *)GetValAdder(pszBuffer)); break; }
	case 7: { strValue = to_string(*(double *)GetValAdder(pszBuffer)); break; }
	case 8: { strValue = to_string(*(int *)GetValAdder(pszBuffer)); break; }
	case 9: { strValue = to_string(*(float *)GetValAdder(pszBuffer)); break; }
	case 10: 
	case 11: { strValue = (char *)GetValAdder(pszBuffer); break; }
	}
	return strValue.size() != 0;
}

bool CValueSet::DelVar(const char * pszName)
{
	bool bRetVal = false;
	char * pszVal = nullptr;
	try
	{
		Lock();
		if (bRetVal = (pszName == nullptr || strlen(pszName) == 0))
		{
			for (auto it = m_mpValue.begin(); it != m_mpValue.end();)
			{
				DelValue(it->second);
				it->second = nullptr;
				it = m_mpValue.erase(it);
			}
		}				
		else if ((pszVal = m_mpValue[pszName]) != nullptr)
		{
			DelValue(pszVal);
			m_mpValue.erase(pszName);
		}			
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock();
	return bRetVal;
}

bool CValueSet::SetValue(const char * pszName, string & strVal, bool bExistFlg)
{
	return SetValue(pszName, strVal.c_str(), strVal.length(), bExistFlg);
}

bool CValueSet::GetValue(const char * pszName, string & strVal)
{
	bool bRetVal = false;
	unordered_map<string, char *>::iterator it;
	try
	{
		Lock();
		if (bRetVal = _ExistValue(pszName, &it)) 
			strVal.assign((char *)GetValAdder(it->second), GetValSize(it->second));
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock();
	return bRetVal;
}

bool CValueSet::SetValue(const char * pszName, IBaseObject * ptrValue, bool bAutoFreeFlg, bool bExistFlg)
{	
	bool bRetVal = false;
	unordered_map<string, char *>::iterator it;
	try
	{
		Lock(); 
		if (!bExistFlg || !_ExistValue(pszName, &it))
		{
			char * pszBuffer = new char[BUFFER_LEN];
			bRetVal = InitValue(pszBuffer, (void *)ptrValue, 16, sizeof(IBaseObject *), nullptr, bAutoFreeFlg);
			if (!bRetVal)
			{
				delete pszBuffer;
				pszBuffer = nullptr;
			}
		}
		else bRetVal = UpdValue(it->second, (void *)ptrValue, 16, sizeof(IBaseObject *), nullptr, bAutoFreeFlg);
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock(); 
	return bRetVal; 
}

bool CValueSet::GetValue(const char * pszName, IBaseObject ** ptrValue)
{
	bool bRetVal = false; 
	unordered_map<string, char *>::iterator it;
	try
	{
		Lock();
		if (bRetVal = _ExistValue(pszName, &it))
			(*ptrValue) = reinterpret_cast<IBaseObject *>(GetValAdder(it->second));
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock();
	return bRetVal;
}

bool CValueSet::SetValue(const char * pszName, void * ptrVal, PDeleter refDeleter)
{
	bool bRetVal = false; 
	unordered_map<string, char *>::iterator it;
	try
	{
		Lock(); 
		if (_ExistValue(pszName, &it)) bRetVal = UpdValue(it->second, ptrVal, 15, sizeof(void *), refDeleter, true);
		else
		{
			char * pszBuffer = new char[BUFFER_LEN];
			if (bRetVal = InitValue(pszBuffer, ptrVal, 15, sizeof(void *), refDeleter, true))
				m_mpValue[pszName] = pszBuffer;
			else
			{
				delete pszBuffer;
				pszBuffer = nullptr;
			}
		}
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock();
	return bRetVal;
}

bool CValueSet::GetValue(const char * pszName, void ** ptrValue)
{
	bool bRetVal = false;
	unordered_map<string, char *>::iterator it;
	try
	{
		Lock();
		if (bRetVal = _ExistValue(pszName, &it))
			(*ptrValue) = GetValAdder(it->second);
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock(); 
	return bRetVal;
}

const bool CValueSet::CurrToStr(const char * pszName, string & strValue, int iDigits, int iCarryNum)
{
	bool bRetVal = false;
	unordered_map<string, char *>::iterator it;
	try
	{
		Lock();
		//bRetVal = _ExistValue(pszName, &it) ? it->second->CurrToStr(strValue, iDigits, iCarryNum) : false;
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock();
	return bRetVal;
}

const bool CValueSet::CurrToStr(const char * pszName, char * pszValue, int iLen, int iDigits, int iCarryNum)
{
	bool bRetVal = false;
	unordered_map<string, char *>::iterator it;
	try
	{
		Lock();
		//bRetVal = _ExistValue(pszName, &it) ? it->second->CurrToStr(pszValue, iLen, iDigits, iCarryNum) : false;
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock();
	return bRetVal;
}

bool CValueSet::CompareExchange(const char * pszName, const string & strValue)
{
	bool bRetVal = false;
	unordered_map<string, char *>::iterator it;
	string value("");
	try
	{
		Lock();
		bRetVal = CompareExchange(pszName, strValue.c_str(), strValue.length());
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock();
	return bRetVal;
}

bool CValueSet::CompareExchange(const char * pszName, IBaseObject * ptrValue, bool bAutoFreeFlg)
{
	bool bRetVal = false;
	IBaseObject * value = nullptr;
	unordered_map<string, char *>::iterator it;
	try
	{
		Lock();
		bRetVal = !_ExistValue(pszName, &it);
		if (bRetVal)
		{
			bRetVal = SetValue(pszName, ptrValue, bAutoFreeFlg);
		}
		else if (GetValAdder(it->second) != ptrValue)
		{
			bRetVal = UpdValue(it->second, ptrValue, 16, sizeof(IBaseObject *), nullptr, bAutoFreeFlg);
		}
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock();
	return bRetVal;
}

bool CValueSet::CompareExchange(const char * pszName, void * ptrVal, PDeleter refDeleter)
{
	bool bRetVal = false;
	void * value = nullptr;
	unordered_map<string, char *>::iterator it;
	try
	{
		Lock();
		bRetVal = !_ExistValue(pszName, &it);
		if (bRetVal)
		{
			bRetVal = SetValue(pszName, ptrVal, refDeleter);
		}
		else if (GetValAdder(it->second) != ptrVal)
		{
			bRetVal = UpdValue(it->second, ptrVal, 15, sizeof(IBaseObject *), refDeleter, true);
		}
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock();
	return bRetVal;
}

bool CValueSet::MoveValue(const char * pszName, IValue ** ptrValue)
{
	bool bRetVal = false;
	unordered_map<string, char *>::iterator it;	
	try
	{
		Lock(); 
		bRetVal = !_ExistValue(pszName, &it);
		if (bRetVal)
		{
			(*ptrValue) = new CValue(it->second);
			m_mpValue.erase(it);
		}
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock();
	return bRetVal;
}

bool CValueSet::_DelVar(const char * pszName, bool bAllClear)
{
	bool bRetVal = false;
	unordered_map<string, char *>::iterator it;
	if (bAllClear)
	{
		for (auto it = m_mpValue.begin(); it != m_mpValue.end();)
		{
			DelValue(it->second);
			it = m_mpValue.erase(it);
		}
	}
	else if (_ExistValue(pszName, &it))
	{
		DelValue(it->second);
		m_mpValue.erase(it);
	}
	return bRetVal;
}

void FreeBuffer(void * ptrVal)
{
	IBaseObject * ptrObj = reinterpret_cast<IBaseObject *>(ptrVal);
	delete ptrObj;
	ptrObj = nullptr;
__end:
	return;
}

bool CValueSet::InitValue(char * pszBuffer, void * ptrVal, const int iType, const int iSize, PDeleter refDeleter, bool bAutoFreeFlg)
{	
	bool bRetVal = false;
	memset((void *)&pszBuffer, 0, BUFFER_LEN);
	pszBuffer[IDX_AUTO_FREE_FLG] = bAutoFreeFlg ? 1 : 0;
	memcpy((void *)&pszBuffer[IDX_TAG], (void *)&iType, sizeof(int));
	memcpy((void *)&pszBuffer[IDX_LENGTH], (void *)&iSize, sizeof(int));
	switch (iType)
	{
	case 1:	case 2:	case 3:	case 4:	case 5:	case 6:	case 7:
	case 8:	case 9: case 10: case 11: case 12: case 13: case 14:
	{
		char * pszVal = new char[iSize];
		memcpy((void *)pszVal, ptrVal, iSize);
		memcpy((void *)&pszBuffer[IDX_VALUE], (void *)&pszVal, sizeof(void *));
		break;
	}
	case 15:
	{
		if (!refDeleter)
		{
			char * pszVal = new char[iSize];
			memcpy((void *)pszVal, ptrVal, iSize);
			memcpy((void *)&pszBuffer[IDX_VALUE], (void *)&pszVal, sizeof(void *));
		}
		else
		{
			memcpy((void *)&pszBuffer[IDX_DELETE_FUN], (void *)&refDeleter, sizeof(PDeleter));
			memcpy((void *)&pszBuffer[IDX_VALUE], &ptrVal, sizeof(void *));
		}
		break;
	}
	case 16:
	{
		memcpy((void *)&pszBuffer[IDX_DELETE_FUN], (void *)&FreeBuffer, sizeof(PDeleter));
		memcpy((void *)&pszBuffer[IDX_VALUE], &ptrVal, sizeof(IBaseObject *));
		break;
	}
	}
	bRetVal = true;
__end:
	return bRetVal;
}

bool CValueSet::UpdValue(char * pszBuffer, void * ptrVal, const int iType, const int iSize, PDeleter refDeleter, bool bAutoFreeFlg)
{
	bool bRetVal = DelValue(pszBuffer);
	if (!bRetVal) goto __end;
	InitValue(pszBuffer, ptrVal, iType, iSize, refDeleter, bAutoFreeFlg);
	bRetVal = true;
__end:
	return bRetVal;
}

const bool CValueSet::DelValue(char * pszBuffer)
{
	bool bRetVal = false;
	PDeleter ptrDeleter = nullptr;
	void * ptrVal = nullptr;
	bool bFreeFlg = false;
	if (IsEmpty(pszBuffer)) goto __end;
	ptrDeleter = GetDeleter(pszBuffer);
	ptrVal = GetValAdder(pszBuffer);
	bFreeFlg = GetAutoFreeFlg(pszBuffer);
	if (ptrDeleter) ptrDeleter(ptrVal);
	else delete (char *)ptrVal;
	ptrVal = nullptr;
	if (!bFreeFlg)
	{
		bRetVal = true;
		goto __end;
	}
	delete pszBuffer;
	pszBuffer = nullptr;
	bRetVal = true;
__end:
	return bRetVal;
}

int CValueSet::GetTypeId(char * pszBuffer)
{
	int iRetVal = 0;
	memcpy((void *)&iRetVal, (void *)&pszBuffer[IDX_TAG], sizeof(char));
	return iRetVal;
}

const char * CValueSet::GetType(char * pszBuffer)
{
	return m_mpIdDataType[GetTypeId(pszBuffer)].c_str();
}

int CValueSet::GetValSize(char * pszBuffer)
{
	int iRetVal = 0;
	memcpy((void *)&iRetVal, (void *)&pszBuffer[IDX_LENGTH], sizeof(int));
	return iRetVal;
}

void * CValueSet::GetValAdder(char * pszBuffer)
{
	void * ptrRetVal = nullptr;
	memcpy(&ptrRetVal, (void *)&pszBuffer[IDX_VALUE], sizeof(void *));
	return ptrRetVal;
}

PDeleter CValueSet::GetDeleter(char * pszBuffer)
{
	PDeleter ptrRetVal = nullptr;
	memcpy((void *)&ptrRetVal, (void *)&pszBuffer[IDX_DELETE_FUN], sizeof(void *));
	return ptrRetVal;
}

const bool CValueSet::_GetValNameList(void * vtNameList)
{
	bool bRetVal = false;
	vector<string> & NameList = *reinterpret_cast<vector<string> *>(vtNameList);
	if (&NameList == nullptr) goto __end;
	for (auto it : m_mpValue) NameList.push_back(it.first);
	bRetVal = NameList.size() > 0;
__end:
	return bRetVal;
}

const unsigned long CValueSet::SumLength(vector<string> &vtNameList)
{
	unsigned long ulRetVal = 0;
	if (!GetValNameList(reinterpret_cast<void *>(&vtNameList))) goto __end;
	for (auto it : vtNameList) ulRetVal += Length(it.c_str());
__end:
	return ulRetVal;
}

const unsigned long CValueSet::Length(const char * pszName)
{
	char szBufLen[CHAR_LEN_MAX_NUM] = { 0 };
	unsigned long ulRetVal = Size(pszName);
	if (ulRetVal == 0) goto __end;
	ulRetVal += strlen(pszName) + strlen(DataType(pszName)) + 2 * strlen(COL_SEP_STR) + strlen(ROW_SEP_STR);
__end:
	return ulRetVal;
}

const bool CValue::CurrToStr(string & strValue, int iDigits, int iCarryNum)
{
	string strVal("");
	if (!GetValue(strVal)) return false;
	string strFloat("");
	int n = strVal.find(".");
	strValue.assign(strVal, 0, n);
	strFloat.assign(strVal, n, strVal.length());
	int iCount = (strValue.length() / 3) - ((strValue.length() % 3) == 0 ? 1 : 0);
	auto it = strValue.end() - 3;
	for (int i = 1; i <= iCount; i++)
	{
		it = strValue.insert(it, ',');
		if (i < iCount) it -= 3;
	}
	if ((iDigits > 0))
	{
		if ((iDigits + 2) < strFloat.length())
		{
			strFloat[iDigits + 2] = 0;
			strFloat[iDigits] = (strFloat[iDigits + 1] - 48 + iCarryNum) >= 10 ? strFloat[iDigits] + 1 : strFloat[iDigits];
			strFloat[iDigits + 1] = 0;
			if (strFloat[iDigits] == 58)
				for (int i = strlen(strFloat.c_str()) - 1; i > 0; i--)
				{
					if (strFloat[i] == 58)
					{
						strFloat[i] = 48;
						strFloat[i - 1] += 1;
					}
				}
		}
		else
		{
			int iCount = (iDigits + 1) - strFloat.length();
			for (int i = 1; i <= iCount; i++) strFloat.append("0");
		}
		strValue += strFloat;
	}
	return true;
}

const bool CValue::CurrToStr(char * pszValue, int iLen, int iDigits, int iCarryNum)
{
	string strValue("");
	memset((void *)pszValue, 0, iLen);
	if (!CurrToStr(strValue, iDigits, iCarryNum)) return false;
	int iDataLen = strValue.length();
	memcpy((void *)strValue.c_str(), (void *)pszValue, (iLen - 1) > iDataLen ? iDataLen : (iLen - 1));
	return true;
}

bool CTaskQueue::Push(void * ptrVal, PDeleter refDeleter, bool bTopFlg)
{
	bool bRetVal = false;
	char * pszBuffer = new char[BUFFER_LEN];
	int iDataTypeId = 15;
	try
	{				
		Lock(); 
		if (bRetVal = CValueSet::InitValue(pszBuffer, ptrVal, 15, sizeof(void *), refDeleter, true))
		{
			delete pszBuffer;
			pszBuffer = nullptr;
		}	
		else if (bTopFlg) m_quValue.insert(m_quValue.begin(), pszBuffer);
		else m_quValue.push_back(pszBuffer);
	}
	catch (const std::exception& clErrMsg)
	{
	
	}
	Unlock(); 
	return bRetVal; 
}

bool CTaskQueue::Pop(IValue ** ptrTaskValue)
{
	bool bRetVal = false;
	try
	{
		Lock();
		if (m_quValue.size() != 0)
		{
			auto it = m_quValue.begin();
			(*ptrTaskValue) = new CValue(*it);
			m_quValue.erase(it);
		}
	}
	catch (const std::exception& clErrMsg)
	{		
	}
	Unlock();
	return bRetVal;
}

bool CTaskQueue::EmptyQueue()
{
	bool bRetVal = false;
	try
	{
		Lock();
		while (m_quValue.size() != 0)
		{
			CValueSet::DelValue(*m_quValue.begin());
			m_quValue.erase(m_quValue.begin());
		}				
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock();
	return bRetVal;
}

unsigned long CTaskQueue::Depth()
{
	unsigned long ulRetVal = 0;
	try
	{
		Lock();
		ulRetVal = m_quValue.size();
	}
	catch (const std::exception& clErrMsg)
	{
	}
	Unlock();
	return ulRetVal;
}

CTaskQueue::~CTaskQueue()
{
	EmptyQueue();
	InitializeCriticalSection(&m_stSection);
}

const bool CTaskQueue::Init(const void * pvdPara, char * pszMsgTxt, int iMsgTxtSize)
{
	InitializeCriticalSection(&m_stSection);
	return true;
}

bool CTaskQueue::Push(const string &strVal, bool bTopFlg)
{
	bool bRetVal = false;
	char * pszBuffer = new char[BUFFER_LEN];
	int iDataTypeId = 10;
	try
	{
		Lock();
		if (!CValueSet::InitValue(pszBuffer, (void *)strVal.c_str(), iDataTypeId, strVal.length(), nullptr, true))
		{
			delete pszBuffer;
			pszBuffer = nullptr;
		}
		else if (bTopFlg) m_quValue.insert(m_quValue.begin(), pszBuffer);
		else m_quValue.push_back(pszBuffer);
	}
	catch (const std::exception& clErrMsg)
	{

	}
	Unlock();
	return bRetVal;
}

bool CTaskQueue::Push(IBaseObject * ptrValue, bool bTopFlg)
{
	bool bRetVal = false;
	char * pszBuffer = new char[BUFFER_LEN];
	int iDataTypeId = 16;
	try
	{
		Lock();
		if (!CValueSet::InitValue(pszBuffer, (void *)ptrValue, iDataTypeId, sizeof(IBaseObject *), nullptr, true))
		{
			delete pszBuffer;
			pszBuffer = nullptr;
		}
		else if (bTopFlg) m_quValue.insert(m_quValue.begin(), pszBuffer);
		else m_quValue.push_back(pszBuffer);
	}
	catch (const std::exception& clErrMsg)
	{

	}
	Unlock();
	return bRetVal;
}

//const bool CTable::Init(const void * pvdPara, char * pszMsgTxt, int iMsgTxtSize)
//{	
//	InitializeCriticalSection(&m_stSection);
//	return true;
//}
//
//CTable::~CTable()
//{	
//	_ClearTable("", false);
//	DeleteCriticalSection(&m_stSection);
//}
//
//bool CTable::Assign(ITable * ptrSouTable)
//{
//	bool bRetVal = true;
//	CTable * ptrTable = reinterpret_cast<CTable *>(ptrSouTable->Self());
//	if (!ptrTable) return bRetVal;
//	try
//	{
//		Lock();
//		ptrTable->Lock();
//		for (auto itTableInfo = ptrTable->m_mpTableInfo.begin(); itTableInfo != ptrTable->m_mpTableInfo.end(); itTableInfo++)
//			bRetVal = bRetVal && CopyRecord(itTableInfo, itTableInfo->first.c_str(), 1, itTableInfo->second.size());
//	}
//	catch (...)
//	{
//	}
//__end:
//	ptrTable->Unlock();
//	Unlock();
//	return bRetVal;
//}
//
//bool CTable::CopyRecord(ITable * ptrSouTable, const char * pszSouName, const char * pszDesName, unsigned long ulBgnNo, unsigned long ulEndNo)
//{
//	bool bRetVal = false;
//	CTable * ptrTable = reinterpret_cast<CTable *>(ptrSouTable->Self());
//	if (!ptrTable) return bRetVal;
//	if (IsEmpty(pszSouName)) return bRetVal;
//	if (IsEmpty(pszDesName)) return bRetVal;
//	try
//	{
//		Lock();
//		ptrTable->Lock();
//		auto itTableInfo = ptrTable->m_mpTableInfo.find(pszSouName);
//		if (itTableInfo == ptrTable->m_mpTableInfo.end()) goto __end;
//		bRetVal = CopyRecord(itTableInfo, pszDesName, ulBgnNo, ulEndNo);
//	}
//	catch (...)
//	{
//	}
//__end:
//	ptrTable->Unlock();
//	Unlock();
//	return bRetVal;
//}
//
//bool CTable::ExistTable(const char * pszTableName)
//{
//	bool bRetVal = false;
//	try
//	{
//		Lock();
//		bRetVal = _ExistTable(pszTableName);
//	}
//	catch (...)
//	{
//	}
//__end:
//	Unlock();
//	return bRetVal;
//}
//
//bool CTable::DelTable(const char * pszTableName)
//{
//	bool bRetVal = false;
//	try
//	{
//		Lock();
//		bRetVal = _ClearTable(pszTableName, true);
//	}
//	catch (...)
//	{
//	}
//__end:
//	Unlock();
//	return bRetVal;
//}
//
//bool CTable::ClearTable(const char * pszTableName)
//{
//	bool bRetVal = false;
//	try
//	{
//		Lock();
//		bRetVal = bRetVal = _ClearTable(pszTableName, false);
//	}
//	catch (...)
//	{
//	}
//__end:
//	Unlock();
//	return bRetVal;
//}
//
//bool CTable::DelRecord(const char * pszTableName, unsigned long ulRecNo)
//{
//	bool bRetVal = false;
//	IValueSet * ptrRow = nullptr;
//	try
//	{
//		Lock();	
//		if (ulRecNo <= 0) goto __end;
//		if (ulRecNo > _RecordCount(pszTableName)) goto __end;
//		auto it = m_mpSort.find(pszTableName);
//		if (it != m_mpSort.end())
//		{
//			ptrRow = it->second[ulRecNo - 1];
//			it->second.erase(it->second.begin() + (ulRecNo - 1));
//		}
//		else ptrRow = _ReadRow(pszTableName, ulRecNo);		
//		vector<IValueSet *> &vtTable = m_mpTableInfo[pszTableName];
//		auto it1 = find(vtTable.begin(), vtTable.end(), ptrRow);
//		vtTable.erase(it1);
//		delete ptrRow;
//		ptrRow = nullptr;		
//		bRetVal = true;
//	}
//	catch (...)
//	{
//	}
//__end:
//	Unlock();
//	return bRetVal;
//}
//
//const bool CTable::GetTableNameList(void * vtNameList)
//{
//
//	bool bRetVal = false;
//	try
//	{
//		Lock();
//		bRetVal = _GetTableNameList(vtNameList);
//	}
//	catch (...)
//	{
//	}
//__end:
//	Unlock();
//	return bRetVal;
//}
//
//unsigned long CTable::TableCount()
//{
//	unsigned long ulRetVal = 0;
//	try
//	{
//		Lock();
//		ulRetVal = m_mpTableInfo.size();
//	}
//	catch (...)
//	{
//	}
//__end:
//	Unlock();
//	return ulRetVal;
//}
//
//unsigned long CTable::RecordCount(const char * pszTableName)
//{
//	unsigned long ulRetVal = 0;
//	try
//	{
//		Lock();
//		ulRetVal = _RecordCount(pszTableName);
//	}
//	catch (...)
//	{
//	}
//__end:
//	Unlock();
//	return ulRetVal;
//}
//
//IValueSet * CTable::NewRow(unsigned long ulRecNo)
//{
//	IValueSet * ptrRetVal = nullptr;
//	CValueSet * ptrNewRow = new CValueSet();	
//	if (ptrNewRow->Init(nullptr, nullptr, 0))
//	{
//		ptrNewRow->SetSequence(ulRecNo);
//		ptrRetVal = ptrNewRow;
//	}	
//	return ptrRetVal;
//}
//
//const bool CTable::Save(const char * pszTableName, IValueSet ** ptrNewRow)
//{
//	bool bRetVal = false;
//
//	try
//	{
//		Lock();
//		bRetVal = _Post(pszTableName, ptrNewRow);
//	}
//	catch (...)
//	{
//	}
//	Unlock();
//	return bRetVal;
//}
//
//const bool CTable::EnCode(char ** pszBuf, unsigned long & ulLen, const char * pszTableName)
//{
//	bool bRetVal = false;
////	ulLen = 0;
////	unordered_map<string, vector<string>> vtTableName;
////	(*pszBuf) = nullptr;
////	char szFoundFlg[3] = { '\0', '\1', '\1' };
////	char szBufLen[CHAR_LEN_MAX_NUM + 1] = { 0 };//
////	unsigned long ulSize = 0, iCount = 0, iItemLen = 0, iSumLen = 0, i = 1, ulBufLen = 0,
////		          ulTalSepLEN = strlen(TAB_SEP_STR), 
////		          ulRowSepLne = strlen(ROW_SEP_STR), 
////		          ulColSepLen = strlen(COL_SEP_STR), 
////		          ulSplitLen  = strlen(SPLIT_STR);
////	const char * pszDataType = nullptr;
////	IValueSet * ptrRecInfo = nullptr;
////
////	auto _InitInfo = [&](const char * pszName)->void
////	{
////		vector<string> vtFieldName;
////		iSumLen += SumColInfo(pszName, vtFieldName) + SumRowInfo(pszName, vtFieldName);
////		vtTableName[pszName] = move(vtFieldName);
////	};
////
////	if (IsEmpty(pszTableName))
////		for (auto it : m_mpTableInfo) _InitInfo(it.first.c_str());
////	else _InitInfo(pszTableName);
////	if (iSumLen == 0) return bRetVal;
////	iSumLen++;
////	char * pszData = new char[iSumLen];
////	char * pszTemp = pszData;
////	for (auto itTableName : vtTableName)
////	{
////		vector<string> & vtFieldName = itTableName.second;
////		iItemLen = itTableName.first.length();
////		memcpy((void *)pszTemp, itTableName.first.c_str(), iItemLen);
////		pszTemp += iItemLen;
////		memcpy((void *)pszTemp, (void *)COL_SEP_STR, ulColSepLen);
////		pszTemp += ulColSepLen;
////		i = 1;
////		iCount = _RecordCount(itTableName.first.c_str());
////		ptrRecInfo = _ReadRow(itTableName.first.c_str(), i);
////		for (auto it : vtFieldName)
////		{
////			pszDataType = ptrRecInfo->DataType(it.c_str(), false);
////			iItemLen = it.length();
////			memcpy((void *)pszTemp, (void *)it.c_str(), iItemLen);
////			pszTemp += iItemLen;
////			memcpy((void *)pszTemp, (void *)SPLIT_STR, ulSplitLen);
////			pszTemp += ulSplitLen;
////			iItemLen = strlen(pszDataType);
////			memcpy((void *)pszTemp, pszDataType, iItemLen);
////			pszTemp += iItemLen;
////			memcpy((void *)pszTemp, (void *)COL_SEP_STR, ulColSepLen);
////			pszTemp += ulColSepLen;
////		}
////		memcpy((void *)pszTemp, ROW_SEP_STR, ulRowSepLne);
////		pszTemp += ulRowSepLne;
////		do
////		{
////			for (auto it : vtFieldName)
////			{
////				iItemLen = ptrRecInfo->Size(it.c_str(), false);
////				szFoundFlg[0] = ptrRecInfo->GetValue(it.c_str(), pszTemp, iItemLen, false) ? '1' : '0';
////				memcpy((void *)(pszTemp + iItemLen), (void *)szFoundFlg, sizeof(szFoundFlg));
////				pszTemp += iItemLen + sizeof(szFoundFlg);
////			}
////			memcpy((void *)(pszTemp), ROW_SEP_STR, ulRowSepLne);
////			pszTemp += ulRowSepLne;
////			i++;
////			ptrRecInfo = _ReadRow(itTableName.first.c_str(), i);
////		} while (ptrRecInfo);
////		memcpy((void *)pszTemp, TAB_SEP_STR, ulTalSepLEN);
////		pszTemp += ulTalSepLEN;		
////	}
////	pszData[iSumLen - 1] = 0;
////	ulLen = compressBound(iSumLen);
////	itoa(iSumLen, szBufLen, 10);
////	szBufLen[strlen(szBufLen)] = '|';
////	(*pszBuf) = new char[ulLen + strlen(szBufLen)];
////	memset((void *)(*pszBuf), 0, ulLen + strlen(szBufLen));
////	pszTemp = (*pszBuf) + strlen(szBufLen);
////	if ((bRetVal = compress((Bytef *)pszTemp, &ulLen, (Bytef *)pszData, iSumLen)) != Z_OK)
////	{
////		delete[](*pszBuf);
////		(*pszBuf) = nullptr;
////	}
////	else
////	{
////		memcpy((void *)(*pszBuf), szBufLen, strlen(szBufLen));
////		bRetVal = true;
////	}
////	delete[]pszData;
////	pszData = nullptr;	
//
//__end:
//	return bRetVal;
//}
//
////#define __SetValue(datatype, funcname, value)\
////   datatype Value = funcname(value);\
////   ptrNewRow->SetValue(pszName, Value);
//
//const bool CTable::DeCode(char * pszBuf, unsigned long ulLen)
//{
//	bool bRetVal = false;
//	//vector<tuple<const char *, const char *>> vtColInfo;
//	//int i = 0, iCount = 0;
//	//unsigned long ulDataLen = 0, ulPos = 0, ulSizeLen = 0, ulTabLen = 0, ulRowLen = 0, ulColLen = 0, ulValLen = 0,
//	//	ulTalSepLEN = strlen(TAB_SEP_STR), ulRowSepLne = strlen(ROW_SEP_STR), ulColSepLen = strlen(COL_SEP_STR),
//	//	ulSplitLen = strlen(SPLIT_STR);
//	//char szDataLen[CHAR_LEN_MAX_NUM] = { 0 };
//	//const char * pszHis = nullptr, * pszData = nullptr, *pszTabData = nullptr, *pszRowData = nullptr, *pszColData = nullptr, *pszCurData = nullptr;
//	//const char * pszName = nullptr, *pszValue = nullptr, *pszDataType = nullptr;
//	//void * ptrRecInfo = nullptr;
//	//if (pszBuf == nullptr) return bRetVal;
//	//do
//	//{
//	//	szDataLen[i] = pszBuf[i];
//	//	i++;
//	//} while (pszBuf[i] != '|');
//	//pszBuf += i + 1;
//	//ulDataLen = atoi(szDataLen);
//	//pszData = new char[ulDataLen];
//	//pszHis = pszData;
//	//if (uncompress((Bytef *)pszData, &ulDataLen, (Bytef *)pszBuf, ulLen) != Z_OK) goto __end;
//	//while ((pszTabData = _GetVal(&pszData, ulDataLen, TAB_SEP_STR, ulTabLen)) != nullptr)
//	//{		
//	//	vtColInfo.clear();	
//	//	pszRowData = _GetVal(&pszTabData, ulTabLen, ROW_SEP_STR, ulRowLen);
//	//	while ((pszColData = _GetVal(&pszRowData, ulRowLen, COL_SEP_STR, ulColLen)) != nullptr)
//	//	{
//	//		((char *)pszColData)[ulColLen] = '\0';
//	//		tuple<const char *, const char *> tpColInfo;
//	//		const char * pszTmp = _GetVal(&pszColData, ulColLen, SPLIT_STR, ulValLen);
//	//		if (ulValLen != 0)
//	//		{
//	//			((char *)pszTmp)[ulValLen] = '\0';
//	//			get<0>(tpColInfo) = pszTmp;		
//	//			get<1>(tpColInfo) = pszColData;
//	//		}				
//	//		else get<0>(tpColInfo) = pszColData;						
//	//		vtColInfo.push_back(move(tpColInfo));			
//	//	}			
//	//	while ((pszRowData = _GetVal(&pszTabData, ulTabLen, ROW_SEP_STR, ulRowLen)) != nullptr)
//	//	{
//	//		i = 1;
//	//		IValueSet * ptrNewRow = NewRow();
//	//		while ((pszColData = _GetVal(&pszRowData, ulRowLen, COL_SEP_STR, ulColLen)) != nullptr)
//	//		{
//	//			ulSizeLen = ulColLen - 1;
//	//			if (pszColData[ulSizeLen] == '1')
//	//			{
//	//				((char *)pszColData)[ulSizeLen] = '\0';
//	//				pszName = get<0>(vtColInfo[i]);					
//	//				pszDataType = get<1>(vtColInfo[i]);
//	//				if (strcmp(pszDataType, "double") == 0)
//	//				{
//	//					__SetValue(double, stold, pszColData);
//	//				}
//	//				else if (strcmp(pszDataType, "float") == 0)
//	//				{
//	//					__SetValue(float, stof, pszColData);
//	//				}
//	//				else if (strcmp(pszDataType, "bool") == 0)
//	//				{
//	//					__SetValue(bool, stoi, pszColData);
//	//				}
//	//				else if (strcmp(pszDataType, "int") == 0)
//	//				{
//	//					__SetValue(int, stoi, pszColData);
//	//				}
//	//				else if (strcmp(pszDataType, "unsigned int") == 0)
//	//				{
//	//					__SetValue(unsigned int, stoul, pszColData);
//	//				}
//	//				else if (strcmp(pszDataType, "long") == 0)
//	//				{
//	//					__SetValue(long, stol, pszColData);
//	//				}
//	//				else if (strcmp(pszDataType, "unsigned long") == 0)
//	//				{
//	//					__SetValue(unsigned long, stoul, pszColData);
//	//				}
//	//				else if (strcmp(pszDataType, "long long") == 0)
//	//				{
//	//					__SetValue(long long, stoll, pszColData);
//	//				}
//	//				else if (strcmp(pszDataType, "unsigned long long") == 0)
//	//				{
//	//					__SetValue(unsigned long long, stoull, pszColData);
//	//				}
//	//				else if (strcmp(pszDataType, "string") == 0)
//	//				{
//	//					ptrNewRow->SetValue(pszName, move(string(pszColData)));
//	//				}
//	//				else if (strcmp(pszDataType, "char *") == 0 || strcmp(pszDataType, "const char *") == 0)
//	//				{
//	//					ptrNewRow->SetValue(pszName, pszColData, strlen(pszColData));
//	//				}
//	//				else if (strcmp(pszDataType, "void *") == 0 && ulSizeLen > 0)
//	//				{
//	//					ptrNewRow->SetValue(pszName, (void *)pszColData, ulSizeLen, false);
//	//				}
//	//			}
//	//			i++;
//	//		}
//	//		Save(get<0>(vtColInfo[0]), &ptrNewRow);
//	//	}
//	//}
//__end:
//	//if (pszHis)
//	//{
//	//	delete[]pszHis;
//	//	pszHis = nullptr;
//	//}
//	return bRetVal;
//}
//
//const bool CTable::Sort(const char * pszTableName, const char * pszFieldNames, bool bDescFlg)
//{
//	bool bRetVal = false;
//	string strSortVal(""), strVal("");
//	vector<string> vtName;
//	string strFieldNames(pszFieldNames);
//	if (strFieldNames[strFieldNames.length() - 1] != ';') strFieldNames += ";";
//	int iPos = 0;
//	int iPrePos = 0;
//	while ((iPos = strFieldNames.find(";", iPos)) >= 0)
//	{
//		vtName.push_back(strFieldNames.substr(iPrePos, iPos - iPrePos));
//		iPrePos = ++iPos;
//	}	
//	try
//	{
//		Lock();
//		m_bSortFlg = false;
//		m_mpSort.erase(pszTableName);		
//		int i = 1;
//		if (!_ExistTable(pszTableName)) goto __end;
//		multimap<string, IValueSet *> mpSort;
//		IValueSet * ptrRecInfo = _ReadRow(pszTableName, i);
//		for (auto it = vtName.begin(); it != vtName.end();)
//			if (!ptrRecInfo->ExistValue(it->c_str())) it = vtName.erase(it);
//			else it++;
//		if (vtName.size() == 0) goto __end;
//		do
//		{
//			strSortVal = "";
//			for (auto it = vtName.begin(); it != vtName.end(); it++)
//			{
//				strVal = "";
//				if (!ptrRecInfo->GetValue(it->c_str(), strVal)) continue;				
//				if (strstr("double|float|bool|unsigned int|unsigned long|unsigned long long", ptrRecInfo->DataType(it->c_str())) != nullptr)
//				{
//					int iLen = strVal.length();
//					if (iLen < 22)
//					{
//						strVal = "0000000000000000000000" + strVal;
//						for (int i = 0; i < iLen; i++) strVal.erase(strVal.begin());
//					}
//				}
//				strSortVal += strVal;
//			}
//			mpSort.insert(move(pair<string, IValueSet *>(strSortVal, ptrRecInfo)));
//			i++;
//		} while ((ptrRecInfo = _ReadRow(pszTableName, i)) != nullptr);	
//		i = 0;
//		vector<IValueSet *> &vtRecNo = m_mpSort[pszTableName];
//		if (bDescFlg)
//		{
//			for (auto it = mpSort.rbegin(); it != mpSort.rend(); it++)
//			{
//				it->second->SetSequence(i++);
//				vtRecNo.push_back(it->second);
//			}
//		}			
//		else
//		{
//			for (auto it = mpSort.begin(); it != mpSort.end(); it++)
//			{
//				it->second->SetSequence(i++);
//				vtRecNo.push_back(it->second);
//			}				
//		}			
//		m_bSortFlg = true;
//	}
//	catch (const std::exception&)
//	{
//
//	}	
//__end:
//	Unlock();
//	return bRetVal;
//}
//
//const bool CTable::Find(const char * pszTableName, const char * pszFindOpt, void * vtRecNo)
//{
//	bool bRetVal = false;
//	map<string, string> mpFindOpt;
//	vector<unsigned long> & vtRec = * reinterpret_cast<vector<unsigned long> *>(vtRecNo);
//	char szOption[CHAR_LEN_2048] = { 0 }, szName[CHAR_LEN_64] = { 0 }, szValue[1984 + 1] = { 0 };
//	int iCount = SeparateCount(pszFindOpt, ";");
//	if ((!IsEmpty(pszFindOpt)) && (iCount == 0)) iCount++;
//	for (int i = 1; i <= iCount; i++)
//	{
//		SeparateString(szOption, sizeof(szOption), pszFindOpt, ";", i);
//		SeparateString(szName, sizeof(szName), szOption, "=", 1);
//		SeparateString(szValue, sizeof(szValue), szOption, "=", 2);
//		if (IsEmpty(szName) || IsEmpty(szValue)) continue;
//		mpFindOpt[szName] = szValue;
//	}
//
//	try
//	{
//		Lock();		
//		vtRec.clear();
//		if (mpFindOpt.size() == 0) goto __end;		
//		if (!_ExistTable(pszTableName)) goto __end;
//		int i = 1;
//		string strVal("");
//		IValueSet * ptrRecInfo = _ReadRow(pszTableName, i);
//		for (auto it = mpFindOpt.begin(); it != mpFindOpt.end();)
//			if (!ptrRecInfo->ExistValue(it->first.c_str())) it = mpFindOpt.erase(it);
//			else it++;
//		if (mpFindOpt.size() == 0) goto __end;
//		do
//		{
//			bRetVal = true;
//			for (auto it = mpFindOpt.begin(); it != mpFindOpt.end(); it++)
//			{
//				strVal = "";
//				if (!ptrRecInfo->GetValue(it->first.c_str(), strVal)) continue;
//				bRetVal = bRetVal && (strVal == it->second);
//			}
//			if (bRetVal) vtRec.push_back(i);
//			i++;
//		} while ((ptrRecInfo = _ReadRow(pszTableName, i)) != nullptr);
//		bRetVal = vtRec.size() > 0;
//	}
//	catch (const std::exception&)
//	{
//
//	}
//__end:
//	Unlock();
//	return bRetVal;
//}
//
//void * CTable::Self()
//{
//	return reinterpret_cast<void *>(this);
//}
//
//const unsigned long CTable::SumColInfo(const char * pszTableName, vector<string> & vtNameList)
//{
//	unsigned long ulRetVal = 0;
//	IValueSet * ptrRowInfo = _ReadRow(pszTableName, 1);
//	if (!ptrRowInfo) goto __end;
//	if (!ptrRowInfo->GetValNameList(reinterpret_cast<void *>(&vtNameList))) goto __end;
//	ulRetVal = strlen(pszTableName) + strlen(COL_SEP_STR);
//	for (auto it = vtNameList.begin(); it != vtNameList.end();)
//		if (ptrRowInfo->Size(it->c_str()) > 0)
//		{
//			ulRetVal += it->length() + strlen(SPLIT_STR) + strlen(ptrRowInfo->DataType(it->c_str())) + strlen(COL_SEP_STR);
//			it++;
//		}
//		else it = vtNameList.erase(it); 			    
//	ulRetVal += strlen(ROW_SEP_STR);
//__end:
//	return ulRetVal;
//}
//
//const unsigned long CTable::SumRowInfo(const char * pszTableName, vector<string> & vtNameList)
//{
//	unsigned long ulRetVal = 0;
//	unsigned long ulRecCnt = _RecordCount(pszTableName);
//	IValueSet * ptrRecInfo = nullptr;
//	unsigned long ulSize   = 0;
//	for (unsigned long i = 1; i <= ulRecCnt; i++)
//	{
//		ptrRecInfo = ReadRow(pszTableName, i);
//		if (!ptrRecInfo) continue;
//		for (auto it : vtNameList)
//			ulRetVal += ptrRecInfo->Size(it.c_str()) + strlen(COL_SEP_STR) + 1;
//		ulRetVal += strlen(ROW_SEP_STR);
//	}
//	ulRetVal += strlen(TAB_SEP_STR);
//__end:
//	return ulRetVal;
//}
//
//const bool CTable::_Post(const char * pszTableName, IValueSet ** ptrNewRow)
//{
//	bool bRetVal = false;
//	long lRecNo = 0;
//	IValueSet * ptrRowInfo = (*ptrNewRow); 
//	if (!ptrRowInfo) return bRetVal;
//	vector<IValueSet *> & clTableInfo = m_mpTableInfo[pszTableName];
//	IValueSet * ptrRecInfo = ptrRowInfo;
//	lRecNo = ptrRowInfo->GetSequence() - 1;
//	if (lRecNo < 0) clTableInfo.push_back(ptrRecInfo);
//	else clTableInfo.insert(clTableInfo.begin(), lRecNo, ptrRecInfo);
//	(*ptrNewRow) = nullptr;
//	bRetVal = true;
//__end:
//	return bRetVal;
//}
//
//bool CTable::_ExistTable(const char * pszTableName)
//{
//	return m_mpTableInfo.find(pszTableName) != m_mpTableInfo.end();
//}
//
//unsigned long CTable::_RecordCount(const char * pszTableName)
//{
//	unsigned long ulRetVal = 0;
//	if (!_ExistTable(pszTableName)) goto __end;
//	ulRetVal = m_mpTableInfo[pszTableName].size();
//__end:
//	return ulRetVal;
//}
//
//IValueSet * CTable::_ReadRow(const char * pszTableName, unsigned long ulRecNo)
//{
//	IValueSet * ptrRetVal = nullptr;
//	ulRecNo--;
//	auto itTableInfo = m_mpTableInfo.find(pszTableName);
//	if (itTableInfo == m_mpTableInfo.end()) return ptrRetVal;
//	if (ulRecNo < 0 || ulRecNo >= itTableInfo->second.size()) return ptrRetVal;
//	ptrRetVal = itTableInfo->second[ulRecNo];
//	if(m_bSortFlg)	
//	{
//		auto itSort = m_mpSort.find(pszTableName);
//		if (itSort != m_mpSort.end()) ptrRetVal = itSort->second[ulRecNo];
//	}
//	return ptrRetVal;
//}
//
//const bool CTable::_GetTableNameList(void * vtNameList)
//{
//	bool bRetVal = false;
//	vector<string> & NameList = *reinterpret_cast<vector<string> *>(vtNameList);
//	if (&NameList == nullptr) goto __end;
//	NameList.clear();
//	for (auto it : m_mpTableInfo) NameList.push_back(it.first);
//	bRetVal = NameList.size() > 0;
//__end:
//	return bRetVal;
//}
//
//const char * CTable::_GetVal(const char ** pszStr, unsigned long &ulSize, const char * pszSep, unsigned long & ulDataSize)
//{
//	ulDataSize = 0;
//	const char * pszRetVal = (*pszStr);
//	int iPos = Pos((*pszStr), pszSep);
//	if (iPos < 0) return nullptr;
//	ulDataSize = iPos + 1;
//	(*pszStr) += strlen(pszSep) + iPos + 1;
//	ulSize -= (ulDataSize + strlen(pszSep));
//__end:
//	return pszRetVal;
//}
//
//bool CTable::_ClearTable(const char * pszTableName, bool bFlg)
//{
//	bool bRetVal = false;
//	if (IsEmpty(pszTableName))
//	{
//		for (auto itTableInfo : m_mpTableInfo)
//		{
//			while (!itTableInfo.second.empty())
//			{
//				auto it = itTableInfo.second.end() - 1;
//				delete *it;
//				*it = nullptr;
//				itTableInfo.second.resize(itTableInfo.second.size() - 1);
//			}
//			itTableInfo.second.clear();
//		}
//		m_mpTableInfo.clear();
//	}
//	else
//	{
//		auto it = m_mpTableInfo.find(pszTableName);
//		if (it == m_mpTableInfo.end()) goto __end;
//		while (!it->second.empty())
//		{
//			auto itTable = it->second.end() - 1;
//			delete *itTable;
//			*itTable = nullptr;
//			it->second.resize(it->second.size() - 1);
//		}
//		it->second.clear();
//		if (bFlg) m_mpTableInfo.erase(it);
//		bRetVal = true;
//	}
//__end:
//	return bRetVal;
//}
//
//bool CTable::CopyRecord(unordered_map<string, vector<IValueSet *>>::iterator  &itTableInfo, const char * pszDesName, unsigned long ulBgnNo, unsigned long ulEndNo)
//{
//	if (&itTableInfo->second == nullptr) return false;
//	if (ulBgnNo <= 0) return false;
//	if (ulEndNo >= itTableInfo->second.size()) return false;	
//	vector<IValueSet *> & vtDesRecInfo = m_mpTableInfo[pszDesName];
//	ulBgnNo--;	ulEndNo--;
//	for (int i = ulBgnNo; i <= ulEndNo; i++)
//	{
//		IValueSet * ptrDesRec = NewRow();
//		if (ptrDesRec == nullptr) continue;
//		if (!ptrDesRec->Assign(itTableInfo->second[i])) continue;
//		vtDesRecInfo.push_back(ptrDesRec);
//	}
//	m_mpTableInfo[pszDesName] = move(vtDesRecInfo);
//	return vtDesRecInfo.size() > 0;
//}
//
//IValueSet * CTable::ReadRow(const char * pszTableName, unsigned long ulRecNo)
//{	
//	IValueSet * ptrRetVal = nullptr;
//	try
//	{
//		Lock();
//		ptrRetVal = _ReadRow(pszTableName, ulRecNo);
//	}
//	catch (...)
//	{
//	}
//__end:
//	Unlock();
//	return ptrRetVal;
//}